package org.vacoor.nothing.web.domain.filter;

import com.google.common.collect.Lists;

import java.util.List;

/**
 */
public class GFR implements GroupedFilter {
    private final Op op;
    private List<Rule> rules;
    private List<GroupedFilter> groups;

    public static GFR conjunction() {
        return create(Op.AND);
    }

    public static GFR disjunction() {
        return create(Op.OR);
    }

    public static GFR create(Op op) {
        return new GFR(op);
    }

    // org.hibernate.criterion.Junction
    public GFR(Op op) {
        this.op = op;
        this.rules = Lists.newArrayList();
        this.groups = Lists.newArrayList();
    }

    @Override
    public Op getOp() {
        return op;
    }

    @Override
    public List<Rule> getRules() {
        return rules;
    }

    @Override
    public List<GroupedFilter> getGroups() {
        return groups;
    }

    @Override
    public GroupedFilter addRule(Rule rule) {
        getRules().add(rule);
        return this;
    }

    @Override
    public GroupedFilter addGroupedFilter(GroupedFilter gf) {
        groups.add(gf);
        return null;
    }

    @Override
    public String toString() {
        if (1 > rules.size() && 1 > groups.size()) {
            return "";
        }
        StringBuilder buff = new StringBuilder();
        append(this, buff);
        return buff.toString();
    }

    void append(GroupedFilter group, StringBuilder buff) {
        Op op = group.getOp();
        List<Rule> rules = group.getRules();
        List<GroupedFilter> subgroup = group.getGroups();
        buff.append("(");
        for (int i = 0; i < rules.size(); i++) {
            Rule rule = rules.get(i);
            Rule.Op ruleOp = rule.getOp();
            buff.append(0 < i ? op : "").append(" ").append(rule.getProperty()).append(" ").append(rule.getOp()).append(" ");
            if (Rule.Op.NU != ruleOp && Rule.Op.NN != ruleOp) {
                buff.append(rule.getValue()).append(" ");
            }
        }

        for (int i = 0; i < subgroup.size(); i++) {
            GroupedFilter g = subgroup.get(i);
            List<Rule> r = g.getRules();
            if (0 < r.size()) {
                buff.append(" ").append(group.getOp()).append(" ");
                append(g, buff);
            }
        }
        buff.append(")");
    }
}
